#include "RemoteThread.h"
#include <stdexcept>
RemoteThread::RemoteThread(HANDLE processHandle, DWORD(__stdcall*functionAddress)(void*)):
m_processHandle(processHandle),
m_threadHandle(NULL),
m_funcAddress(functionAddress)
{

}
RemoteThread::RemoteThread(RemoteThread&& rhs):
m_processHandle(rhs.m_processHandle),
m_threadHandle(rhs.m_threadHandle),
m_funcAddress(rhs.m_funcAddress)
{
	rhs.m_processHandle = NULL;
	rhs.m_threadHandle = NULL;
	rhs.m_funcAddress = 0;
}
RemoteThread::~RemoteThread(void)
{
	if (m_threadHandle != NULL)
		CloseHandle(m_threadHandle);
}
RemoteThread& RemoteThread::operator=(RemoteThread&& rhs)
{
	if (m_threadHandle != NULL)
		CloseHandle(m_threadHandle);

	m_processHandle = rhs.m_processHandle;
	m_threadHandle = rhs.m_threadHandle;
	m_funcAddress = rhs.m_funcAddress;

	rhs.m_processHandle = NULL;
	rhs.m_threadHandle = NULL;
	rhs.m_funcAddress = 0;

	return *this;
}
DWORD RemoteThread::Call(void* args)
{
	if (m_threadHandle != NULL)
		CloseHandle(m_threadHandle);

	m_threadHandle = CreateRemoteThread(m_processHandle, 0, 0, m_funcAddress, args, 0, 0);
	if (m_threadHandle == NULL)
		throw std::runtime_error("RemoteThread::Call - Thread could not be created.");
	
	DWORD waitState = WaitForSingleObject(m_threadHandle, 5000);
	if (waitState != WAIT_OBJECT_0)
		throw std::runtime_error("RemoteThread::Call - Thread timed out.");

	DWORD exitCode = 0;
	BOOL retVal = GetExitCodeThread(m_threadHandle, &exitCode);
	if (retVal == FALSE || exitCode == 0)
		throw std::runtime_error("RemoteThread::Call - Thread failed to return.");

	//CloseHandle(m_threadHandle);  - Should not be needed.
	return exitCode;
}